import BaseEvent from '@/components/events/BaseEvent'
import { COMPONENT_TYPES, CONTROL_TYPES } from '@/common/const-wb'
import { EVENT_HOVER_TYPES, SAVE_IMG_DATA_TYPES } from '@/common/events'
import { EventBus } from '@/store/index'
import crc32 from '@/components/utils/crc/crc32'
import { randomUploadFileName, getValueFromXml } from '@/plugins/utils'
import { Dialog } from 'vant'
import { isHasOwnProperty, getCompIdByParam } from '@/plugins/utils'

const fileUploadUrl = 'https://sinastorage.com/file.hd.xxx.com/'
const fileUploadS3Url_ = 'https://picupload.xxx.com/interface/upload.php'

const RECURSION_SEARCH_COMP_CIDS = [
  COMPONENT_TYPES.wb_camera,
  COMPONENT_TYPES.wb_scroll_container,
  COMPONENT_TYPES.wb_threes
]

export default class SaveImgEvent extends BaseEvent {
  constructor() {
    super();
    this.hiddenDoms = [];
    this.displayDoms = [];
    this.timeOut = 0;
    this.needCanvasCompData = null;//截打组组件中是都有相机组件和滚动容器组件，有的话触发事件isStartHtml2canvas这个显示对应dom
    this.saveImgType = SAVE_IMG_DATA_TYPES[0].value;
    this.saveImgQuality = 0.8;
    this.saveImgBgColor = null;
  }

  get fileUploadData(){
    return this.store.state.fileUploadData
  }

  excute({item, event, isPostWbEventOrCommonEvents}){
    this.item = item;
    this.event = event;
    if(event.comps[3]) {
      this.saveImgType = event.comps[3].attrs.value;
      this.saveImgQuality = event.comps[3].attrs.quality;
      if(this.saveImgType == SAVE_IMG_DATA_TYPES[0].value) {
        this.saveImgBgColor = '#ffffff';
      }
    }

    this.isPostWbEventOrCommonEvents = isPostWbEventOrCommonEvents;

    // 截图 默认如果什么参数都没有传就是截取整个页面，传了截图容器id，就会截取截图容器id内的内容，
    // 如果传了替换图片组件id，那么截取后canvas的图片会填充到这个组件中
    const pushCompId = getCompIdByParam(event.comps[0].attrs.value);
    const cropCompId = getCompIdByParam(event.comps[1].attrs.value);
    const hiddenCompIdsStr = event.comps[1].attrs.hiddenCompIds;
    const hiddenCompIds = hiddenCompIdsStr ? JSON.parse(hiddenCompIdsStr) : [];
    const repalceImgId = getCompIdByParam(event.comps[2].attrs.value);
    const isUploadImgToServer = isHasOwnProperty(event.comps[2].attrs, 'isUploadImgToServer') ? event.comps[2].attrs.isUploadImgToServer : true;
    let canvasCon = null;
    let cropImgUrl = null;
    if(cropCompId || repalceImgId){
      let cropCompData = null;
      if(cropCompId){
        cropCompData = this.componentMap[cropCompId];
        if(cropCompData){
          let needCropCompData = this.recursionSearchCropCompData(cropCompData);
          if(needCropCompData) {
            this.needCanvasCompData = needCropCompData;
          }
        }
        canvasCon = document.getElementById(cropCompId);
      }

      if(!canvasCon){
        window.scrollTo({top: 0, behavior: 'instant'});
      }

      if(repalceImgId && !isUploadImgToServer){
        this.canvasImgInLocal({canvasCon, cropCompId, repalceImgId, hiddenCompIds})
      }else{
        if(cropCompId && cropCompData.cid == COMPONENT_TYPES.wb_camera){
          //没有打开相册执行下面的事件 直接发博
          cropImgUrl = cropCompData.commonAttr.cropImgUrl;
          if(!cropImgUrl){
            this.isPostWbEventOrCommonEvents({ loadEvent: null, e: null })
          }else{
            this.canvasImgOrUploadToServer({ canvasCon, cropCompId, repalceImgId, hiddenCompIds, pushCompId })
          }
        }else{
          this.canvasImgOrUploadToServer({ canvasCon, cropCompId, repalceImgId, hiddenCompIds, pushCompId })
        }
      }
    }else{
      this.canvasImgOrUploadToServer({ canvasCon, cropCompId, repalceImgId, hiddenCompIds, pushCompId })
    }
  }

  canvasImgInLocal({ canvasCon, cropCompId, repalceImgId, hiddenCompIds }) {
    const el = canvasCon ? canvasCon : document.getElementById("jianye-container");

    this.onHiddenDoms(canvasCon, el, hiddenCompIds);
    let cropCompData;
    if(cropCompId) {
      cropCompData = this.componentMap[cropCompId];
    }
    this.onDisplayDoms(el, cropCompData);

    window.setTimeout(() => {
      window.html2canvas(el, {
        backgroundColor: this.saveImgBgColor,//设置图片背景为透明
        useCORS: true,
        async: true,
        logging: false,
      }).then((canvas) => {
        this.onRecoverDoms(cropCompData);
        let canResultBase64 = canvas.toDataURL('image/' + this.saveImgType, Number(this.saveImgQuality));
        const url = canResultBase64;
        this.onSaveSuccessCb(repalceImgId, url);
        this.isPostWbEventOrCommonEvents({ loadEvent: null, e: null })
      });
    }, this.timeOut)
  }

  canvasImgOrUploadToServer({ canvasCon, cropCompId, repalceImgId, hiddenCompIds, pushCompId }) {
    let el = canvasCon ? canvasCon : document.getElementById("jianye-container");

    this.onHiddenDoms(canvasCon, el, hiddenCompIds);
    let cropCompData, repalceImgData
    if(cropCompId){
      cropCompData = this.componentMap[cropCompId];
    }
    if(repalceImgId){
      repalceImgData = this.componentMap[repalceImgId]
    }
    this.onDisplayDoms(el, cropCompData);
    const this_ = this;
    window.setTimeout(() => {
      window.html2canvas(el, {
        backgroundColor: this.saveImgBgColor,//设置图片背景为透明
        useCORS: true,
        async: true,
        logging: false,
      }).then((canvas) => {
        this_.onRecoverDoms(cropCompData);
        const canResultBase64 = canvas.toDataURL('image/' + this.saveImgType, Number(this.saveImgQuality));
        canvas.toBlob((blobObj) => {
          if(pushCompId || this_.item.events[EVENT_HOVER_TYPES.push.type] || this_.item.events[EVENT_HOVER_TYPES.openPush.type]){
            this_.setUploadParams(blobObj, canResultBase64, pushCompId, repalceImgId);
          }else if(this_.item.events[EVENT_HOVER_TYPES.submit.type] || repalceImgData.commonAttr.isForm){
            this_.setSaveUploadParams(blobObj, repalceImgId);
          }else {
            // if(isWeibo()){
              // this_.setSaveUploadParams(blobObj, repalceImgId);
            // }else{
              this_.onSaveSuccessCb(repalceImgId, canResultBase64);
            // }
            this.isPostWbEventOrCommonEvents({ loadEvent: null, e: null })
          }
        }, 'image/' + this.saveImgType, Number(this.saveImgQuality));

      });
    }, this.timeOut)
  }

  setSaveUploadParams(blobObj, repalceImgId){
    let picType = '.jpeg'
    if(this.saveImgType != SAVE_IMG_DATA_TYPES[0].value) {
      picType = '.png'
    }
    let filename =  randomUploadFileName(this.siteInfo.id) + picType;
    let fileUploadData = _.cloneDeep(this.fileUploadData);
    fileUploadData.key += filename;

    const this_ = this;
    let option = {
      action: fileUploadUrl,
      onSuccess: (response) => {
        let url = getValueFromXml(response);
        url = _.replace(url, 'http', 'https');
        url = _.replace(url, 'file', 'static');
        url = _.replace(url, '.s3.sinaapp.com', '');

        this_.item.commonAttr.cropUploadImgUrl = url;
        this_.onSaveSuccessCb(repalceImgId, url);
        this.isPostWbEventOrCommonEvents({ loadEvent: null, e: null })
      },
      onError: (e) => {
        console.log(e);
      },
      data: fileUploadData,
      fileKey: "file",
      file: blobObj,
    }
    this.upload(option);
  }

  onSaveSuccessCb(repalceImgId, url){
    this.store.commit("updatePageCropRecoverUrl", {id: repalceImgId, pageId: this.pageIndex+1});
    if(repalceImgId && repalceImgId.length > 0){
      this.store.commit("updateComponentAttrUrl", {id: repalceImgId, commonAttr: { url }});
      const compData = this.componentMap[repalceImgId]
      if(compData && compData.commonAttr.isForm) {
        this.store.commit("updateFormValue", {
          id: repalceImgId,
          url,
        });
      }
    }
  }

  setUploadParams(blobObj, base64, pushCompId, repalceImgId) {
    let unit8Array = this.base64ToUInt8Array(base64);
    let this_ = this;
    let url = fileUploadS3Url_ + "?ent=miniblog&appid=" + this_.appid + "&uid=" + this_.userInfo.uid + "&file_source=67&cs=" + crc32(unit8Array);
    // let reader = new FileReader();
    // reader.onload = function() {
      let option = {
        action: url,
        onSuccess: (response) => {
          if(!response.ret){
            this_.showAlert(response.errno);
            return
          }

          let data = response.pic;

          let pic_id = data.pid
          let original_pic = this.getImgURL(pic_id, 'large')
          //将截图上传的图片存在saveImg事件的组件上，不更新UI，不需要commit
          this.item.commonAttr.cropUploadImgUrl = original_pic;

          let jumpUrl = "upload"
          let comType = "onload"
          let wModule = "upload"
          this_.onPostStatics(null, { comType, wModule,  jumpUrl })

          if(repalceImgId) {
            this_.onSaveSuccessCb(repalceImgId, original_pic);
          }
          this_.onSuccessCb(pic_id, original_pic, pushCompId)
        },
        onError: (err) => {
          this_.showAlert(err);
        },
        type: 'image',
        data: blobObj,
        withCredentials: true,
        headers: {"Content-Type": "multipart/form-data"}
      }
      this_.upload(option);
    // }
    // reader.readAsArrayBuffer(blobObj);
  }

  getImgURL(pid, type, https) {
    var url
    if (typeof(type) == "undefined") type = 'bmiddle';
    if (typeof(https) == "undefined") https = false;
    if (pid[9] == 'w' || (pid[9] == 'y' && pid.length >= 32)) {
      var zone = (crc32(pid) & 3) + 1;
      var ext = (pid[21] == 'g') ? 'gif' : 'jpg';
      if (https) {
        url = pid[9] == 'w' ? 'https://ww' + zone + '.sinaimg.cn/' + type + '/' + pid + '.' + ext :
          'https://wx' + zone + '.sinaimg.cn/' + type + '/' + pid + '.' + ext;
      } else {
        url = pid[9] == 'w' ? 'http://ww' + zone + '.sinaimg.cn/' + type + '/' + pid + '.' + ext :
          'http://wx' + zone + '.sinaimg.cn/' + type + '/' + pid + '.' + ext;
      }
    } else {
      var zone = (parseInt(pid.substr(-2, 2), 16) & 0xf) + 1;
      if (https) {
        url = 'https://ss' + zone + '.sinaimg.cn/' + type + '/' + pid + '&690';
      } else {
        url = 'http://ss' + zone + '.sinaimg.cn/' + type + '/' + pid + '&690';
      }
    }
    return url;
  }

  base64ToUInt8Array(base64){
    let BASE64_MARKER = ';base64,';
    let raw;
    let parts;
    parts = base64.split(BASE64_MARKER);
    raw = window.atob(parts[1]);
    let rawLength = raw.length;
    var uInt8Array = new Uint8Array(rawLength);
    for (var i = 0; i < rawLength; ++i) {
      uInt8Array[i] = raw.charCodeAt(i);
    }
    return uInt8Array
  }

  showAlert(error) {
    Dialog.alert({
      title: '',
      message: error,
    });
  }


  onHiddenDoms(canvasCon, el, hiddenCompIds){
    let hiddenDoms = this.hiddenDoms;
    while(hiddenDoms.length > 0){
      hiddenDoms.pop();
    }
    if(!canvasCon && hiddenCompIds){
      _.forEach(hiddenCompIds, (compId) => {
        let dom = document.getElementById(compId);
        dom.style.display = "none";
        hiddenDoms.push(dom);
      })
    }
    // const canvasDoms = el.querySelectorAll('canvas');
    // _.forEach(canvasDoms, (canvas) => {
    //   canvas.style.display = "none";
    //   hiddenDoms.push(canvas);
    // })
    //处理动画效果截图有问题的bug
    const lis = el.querySelectorAll('.swiper-li');
    _.forEach(lis, (li) => {
      li.classList.toggle("animate__fadeIn");
      li.classList.toggle("animate__animated");
    });
  }

  onDisplayDoms(el, cropCompData){
    let displayDoms = this.displayDoms;
    while(displayDoms.length > 0){
      displayDoms.pop();
    }
    if(cropCompData){
      if(this.needCanvasCompData){
        EventBus.$emit("isStartHtml2canvas", { isStart: true, compId: this.needCanvasCompData.id});
        this.timeOut = 0
      }
    }

    if(el.className == "group-component-con"){
      if(el.style.opacity === "0"){
        el.style.opacity = 1;
        displayDoms.push(el);
      }
    }
    const groupsDoms = el.querySelectorAll('.group-component-con');
    _.forEach(groupsDoms, (dom) => {
      if(dom.style.opacity === "0"){
        dom.style.opacity = 1;
        displayDoms.push(dom);
      }
    })
    const textDoms = el.querySelectorAll('.wb-text');
    _.forEach(textDoms, (dom) => {
      if(dom.style.opacity === "0"){
        dom.style.opacity = 1;
        displayDoms.push(dom);
      }
    })
    const imgDoms = el.querySelectorAll('.wb-img');
    _.forEach(imgDoms, (dom) => {
      if(dom.style.opacity === "0"){
        dom.style.opacity = 1;
        displayDoms.push(dom);
      }
    })
  }

  onRecoverDoms(cropCompData){
    let hiddenDoms = this.hiddenDoms;
    let displayDoms = this.displayDoms;
    _.forEach(hiddenDoms, (dom) => {
      dom.style.display = "block";
    });
    _.forEach(displayDoms, (dom) => {
      dom.style.opacity = 0;
    });
    if(cropCompData){
      if(this.needCanvasCompData){
        EventBus.$emit("isStartHtml2canvas", { isStart: false, compId: this.needCanvasCompData.id});
      }
    }
  }

  onSuccessCb(pic_id, original_pic, pushCompId){
    if(pushCompId || this.item.events[EVENT_HOVER_TYPES.push.type]){
      this.canvasImgComponentMap[pushCompId] = pushCompId;
      let picItem = { pic_id, pic_url: original_pic }
      this.store.commit("updatePushPicItem", { id: this.item.id, controlId: CONTROL_TYPES.wb_push, picItem })
    }else if(this.item.events[EVENT_HOVER_TYPES.openPush.type]){
      let cameraItem = {
        thumbnail: original_pic,
        original: original_pic,
        pid: pic_id,
      }
      let pics = [cameraItem]
      this.store.commit("updateFrontData", { id: this.item.id, data: {pics} })
    }
    //从camara过来的，需要发事件继续执行组件剩余的事件
    this.isPostWbEventOrCommonEvents({ loadEvent: null, e: null })
  }

  upload(option){
    var xhr = new XMLHttpRequest();
    if(option.withCredentials){
      xhr.withCredentials = true;
    }
    var action = option.action;
    let type = option.type ? option.type : 'formdata';
    let data = null;
    if(type == 'image'){
      data = option.data
    }else{
      var formData = new FormData();
      if (option.data) {
        Object.keys(option.data).forEach((key) => {
          formData.append(key, option.data[key]);
        });
      }
      formData.append(option.fileKey, option.file);
      data = formData;
    }
    xhr.onerror = (e) => {
      option.onError(e);
    };
    xhr.onload = () => {
      if (xhr.status < 200 || xhr.status >= 300) {
        return option.onError(this.getError(action, option, xhr));
      }
      option.onSuccess(this.getBody(xhr));
    };
    xhr.open('post', action, true);
    var headers = option.headers || {};
    for (var key in headers) {
      if (isHasOwnProperty(headers, key) && headers[key] !== null) {
        xhr.setRequestHeader(key, headers[key]);
      }
    }
    xhr.send(data);
    return xhr;
  }

  getBody(xhr) {
    let text = xhr.responseText || xhr.response;
    if (!text) {
      return text;
    }
    try {
      return JSON.parse(text);
    } catch (e) {
      return text;
    }
  }

  getError(action, option, xhr) {
    let msg = void 0;
    if (xhr.response) {
      msg = '' + (xhr.response.error || xhr.response);
    } else if (xhr.responseText) {
      msg = '' + xhr.responseText;
    } else {
      msg = 'fail to post ' + action + ' ' + xhr.status;
    }
    let err = new Error(msg);
    err.status = xhr.status;
    err.method = 'post';
    err.url = action;
    return err;
  }

  dataURLToBlob(dataURL) {
    let BASE64_MARKER = ';base64,';
    let raw;
    let contentType;
    let parts;
    if (dataURL.indexOf(BASE64_MARKER) == -1) {
      parts = dataURL.split(',');
      contentType = parts[0].split(':')[1];
      raw = decodeURIComponent(parts[1]);

      return new Blob([raw], { type: contentType });
    }
    parts = dataURL.split(BASE64_MARKER);
    contentType = parts[0].split(':')[1];
    raw = window.atob(parts[1]);
    let rawLength = raw.length;
    var uInt8Array = new Uint8Array(rawLength);
    for (var i = 0; i < rawLength; ++i) {
      uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], { type: contentType });
  }
  //递归检索是否有相机组件和滚动容器组件
  recursionSearchCropCompData(componentData_){
    let components = componentData_.components;
    if(RECURSION_SEARCH_COMP_CIDS.indexOf(componentData_.cid) !== -1){
      return componentData_
    } else if(components && components.length > 0) {
      return this.recursionSearchCropCompData_(components);
    }
    return null;
  }

  recursionSearchCropCompData_ (components) {
    let componentData_;
    for(let i = 0, len = components.length; i < len; i++){
      componentData_ = components[i];
      if(RECURSION_SEARCH_COMP_CIDS.indexOf(componentData_.cid) !== -1){
        return componentData_
      }else if(componentData_.components && componentData_.components.length > 0){
        return this.recursionSearchCropCompData_(componentData_.components);
      }
    }
    return null;
  }

  destroy(){
    super.destroy();
  }
}
